package co.touchlab.skie.buildsetup.tests.plugins.tests

import co.touchlab.skie.buildsetup.main.plugins.base.BaseKotlinPlugin
import co.touchlab.skie.buildsetup.main.plugins.utility.UtilityBuildConfigPlugin
import co.touchlab.skie.buildsetup.main.plugins.utility.UtilityExperimentalContextReceiversPlugin
import co.touchlab.skie.buildsetup.main.plugins.utility.UtilityMinimumTargetKotlinVersionPlugin
import co.touchlab.skie.buildsetup.main.plugins.utility.UtilityOptInCompilerApiPlugin
import co.touchlab.skie.buildsetup.util.enquoted
import co.touchlab.skie.buildsetup.util.getKotlinNativeCompilerEmbeddableDependency
import co.touchlab.skie.buildsetup.util.implementation
import co.touchlab.skie.buildsetup.util.kotlinNativeCompilerHome
import co.touchlab.skie.buildsetup.util.version.KotlinToolingVersion
import co.touchlab.skie.buildsetup.util.version.SupportedKotlinVersionProvider
import com.github.gmazzo.buildconfig.BuildConfigExtension
import com.github.gmazzo.buildconfig.generators.BuildConfigKotlinGenerator
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper

abstract class TestsAcceptanceTestsFrameworkPlugin : Plugin<Project> {

    override fun apply(project: Project): Unit = with(project) {
        apply<BaseKotlinPlugin>()
        apply<UtilityMinimumTargetKotlinVersionPlugin>()
        apply<UtilityOptInCompilerApiPlugin>()
        apply<UtilityExperimentalContextReceiversPlugin>()
        apply<UtilityBuildConfigPlugin>()
        apply<KotlinPluginWrapper>()

        val primaryCompilerVersion = SupportedKotlinVersionProvider.getPrimaryKotlinVersion(project).compilerVersion

        configureBuildConfig(primaryCompilerVersion)
        configureDependencies(primaryCompilerVersion)
    }

    private fun Project.configureBuildConfig(primaryCompilerVersion: KotlinToolingVersion) {
        val sourceSets = extensions.getByName("sourceSets") as SourceSetContainer
        val mainSourceSet = sourceSets.named("main")

        extensions.configure<BuildConfigExtension> {
            generator.set(BuildConfigKotlinGenerator(internalVisibility = false))

            buildConfigField(
                type = "String",
                name = "KONAN_HOME",
                value = project.kotlinNativeCompilerHome(primaryCompilerVersion).path,
            )

            buildConfigField(
                type = "String",
                name = "RESOURCES",
                value = mainSourceSet.map { it.output.resourcesDir!!.absolutePath.enquoted() },
            )
        }
    }

    private fun Project.configureDependencies(primaryCompilerVersion: KotlinToolingVersion) {
        dependencies {
            implementation(getKotlinNativeCompilerEmbeddableDependency(primaryCompilerVersion))

            val trove4j = project.kotlinNativeCompilerHome(primaryCompilerVersion).resolve("konan/lib/trove4j.jar")

            // Removed in Kotlin 2.2.0
            if (trove4j.exists()) {
                implementation(files(trove4j))
            }
        }
    }
}
